package cn.iocoder.yudao.module.wengfu.service.consignmentprocessingreport;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.wengfu.controller.admin.resultsdispatchroomdetails.vo.ResultsDispatchRoomDetailsRespVO;
import cn.iocoder.yudao.module.wengfu.service.resultsdispatchroomdetails.ResultsDispatchRoomDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Valid;

import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import cn.iocoder.yudao.module.wengfu.controller.admin.consignmentprocessingreport.vo.*;
import cn.iocoder.yudao.module.wengfu.dal.dataobject.consignmentprocessingreport.ConsignmentProcessingReportDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wengfu.dal.mysql.consignmentprocessingreport.ConsignmentProcessingReportMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.wengfu.enums.ErrorCodeConstants.*;

/**
 * 委托加工及购进矿石质量报表 Service 实现类
 *
 * @author yzs
 */
@Service
@Validated
@Slf4j
public class ConsignmentProcessingReportServiceImpl implements ConsignmentProcessingReportService {

    @Resource
    private ConsignmentProcessingReportMapper consignmentProcessingReportMapper;

    @Resource
    private ResultsDispatchRoomDetailsService resultsDispatchRoomDetailsService;

    // 常量定义
    private static final int SCALE = 2;
    private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
    private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(SCALE, ROUNDING_MODE);

    // 时间范围常量
    private static final String CURRENT_MONTH_START = "2025-07-25 00:00:00.000";
    private static final String CURRENT_MONTH_END = "2025-08-24 23:59:59.999";
    private static final String YEAR_TO_DATE_START = "2025-01-25 00:00:00.000";
    private static final String YEAR_TO_DATE_END = "2025-07-24 23:59:59.999";
    private static final String LAST_YEAR_START = "2024-01-25 00:00:00.000";
    private static final String LAST_YEAR_END = "2024-07-24 23:59:59.999";

    @Override
    public Long createConsignmentProcessingReport(ConsignmentProcessingReportSaveReqVO createReqVO) {
        ConsignmentProcessingReportDO consignmentProcessingReport = BeanUtils.toBean(createReqVO, ConsignmentProcessingReportDO.class);
        consignmentProcessingReportMapper.insert(consignmentProcessingReport);
        return consignmentProcessingReport.getId();
    }

    @Override
    public void updateConsignmentProcessingReport(ConsignmentProcessingReportSaveReqVO updateReqVO) {
        validateConsignmentProcessingReportExists(updateReqVO.getId());
        ConsignmentProcessingReportDO updateObj = BeanUtils.toBean(updateReqVO, ConsignmentProcessingReportDO.class);
        consignmentProcessingReportMapper.updateById(updateObj);
    }

    @Override
    public void deleteConsignmentProcessingReport(Long id) {
        validateConsignmentProcessingReportExists(id);
        consignmentProcessingReportMapper.deleteById(id);
    }

    @Override
    public void deleteConsignmentProcessingReportListByIds(List<Long> ids) {
        consignmentProcessingReportMapper.deleteByIds(ids);
    }

    private void validateConsignmentProcessingReportExists(Long id) {
        if (consignmentProcessingReportMapper.selectById(id) == null) {
            throw exception(CONSIGNMENT_PROCESSING_REPORT_NOT_EXISTS);
        }
    }

    @Override
    public ConsignmentProcessingReportDO getConsignmentProcessingReport(Long id) {
        return consignmentProcessingReportMapper.selectById(id);
    }

    @Override
    public PageResult<ConsignmentProcessingReportDO> getConsignmentProcessingReportPage(ConsignmentProcessingReportPageReqVO pageReqVO) {
        return consignmentProcessingReportMapper.selectPage(pageReqVO);
    }

    @Override
    public Map<String, BigDecimal> UpdateConsignmentProcessingReport() {
        try {
            // 1. 获取三个时间维度的数据
            Map<String, BigDecimal> currentMonthData = getDataByTimeRange(CURRENT_MONTH_START, CURRENT_MONTH_END);
            Map<String, BigDecimal> yearToDateData = getDataByTimeRange(YEAR_TO_DATE_START, YEAR_TO_DATE_END);
            Map<String, BigDecimal> lastYearData = getDataByTimeRange(LAST_YEAR_START, LAST_YEAR_END);

            // 2. 合并数据到最终结果
            Map<String, BigDecimal> finalResult = mergeAllData(currentMonthData, yearToDateData, lastYearData);

            log.info("委托加工及购进矿石质量报表数据更新完成，共处理 {} 条数据", finalResult.size());
            return finalResult;

        } catch (Exception e) {
            log.error("更新委托加工及购进矿石质量报表失败", e);
            return Collections.emptyMap();
        }
    }

    @Override
    public void batchSaveConsignmentProcessingReport(@Valid List<ConsignmentProcessingReportSaveReqVO> saveReqVOList) {
        if (saveReqVOList == null || saveReqVOList.isEmpty()) {
            return;
        }
        try {
            // 批量处理，避免一次性插入过多数据
            int batchSize = 100; // 每批处理100条记录
            for (int i = 0; i < saveReqVOList.size(); i += batchSize) {
                int end = Math.min(i + batchSize, saveReqVOList.size());
                List<ConsignmentProcessingReportSaveReqVO> batchList = saveReqVOList.subList(i, end);

                // 批量插入或更新
                processBatchSave(batchList);
            }
        } catch (Exception e) {
           log.error("批量保存委托加工及购进矿石质量报表失败");
        }
    }

    /**
     * 将SaveReqVO转换为DO对象
     */
    private ConsignmentProcessingReportDO convertToDO(ConsignmentProcessingReportSaveReqVO saveReqVO) {
        ConsignmentProcessingReportDO entity = new ConsignmentProcessingReportDO();
        entity.setId(saveReqVO.getId());
        entity.setSerialNumber(saveReqVO.getSerialNumber());
        entity.setProductName(saveReqVO.getProductName());
        entity.setGrade(saveReqVO.getGrade());
        entity.setMonthlyAverage(saveReqVO.getMonthlyAverage());
        entity.setMonthlyQuantity(saveReqVO.getMonthlyQuantity());
        entity.setYearlyCumulativeAverage(saveReqVO.getYearlyCumulativeAverage());
        entity.setYearlyCumulativeQuantity(saveReqVO.getYearlyCumulativeQuantity());
        entity.setLastYearCumulativeAverage(saveReqVO.getLastYearCumulativeAverage());
        entity.setLastYearCumulativeQuantity(saveReqVO.getLastYearCumulativeQuantity());
        entity.setYearCumulativeAverage(saveReqVO.getYearCumulativeAverage());
        entity.setYearCumulativeQuantity(saveReqVO.getYearCumulativeQuantity());
        // 设置其他字段，如创建人、更新时间等
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateTime(LocalDateTime.now());
        // 如果需要设置创建人和更新人，可以在这里设置
         entity.setCreator("system");
         entity.setUpdater("system");
        return entity;
    }

    /**
     * 处理批量保存逻辑
     */
    private void processBatchSave(List<ConsignmentProcessingReportSaveReqVO> batchList) {
        List<ConsignmentProcessingReportDO> entitiesToSave = new ArrayList<>();
        List<ConsignmentProcessingReportDO> entitiesToUpdate = new ArrayList<>();

        for (ConsignmentProcessingReportSaveReqVO saveReqVO : batchList) {
            ConsignmentProcessingReportDO entity = convertToDO(saveReqVO);
            entitiesToSave.add(entity);
        }
        if(!entitiesToSave.isEmpty()){
            //删除表中原有数据
            int i = consignmentProcessingReportMapper.deleteAll();
            log.info("数据删除，删除{}行数",i);
        }

        // 批量插入新记录
        if (!entitiesToSave.isEmpty()) {
            consignmentProcessingReportMapper.insertBatch(entitiesToSave);
        }

        // 批量更新现有记录
        if (!entitiesToUpdate.isEmpty()) {
            for (ConsignmentProcessingReportDO entity : entitiesToUpdate) {
                consignmentProcessingReportMapper.updateById(entity);
            }
        }
    }

    /**
     * 根据时间范围获取数据
     */
    private Map<String, BigDecimal> getDataByTimeRange(String startTime, String endTime) {
        Map<String, BigDecimal> params = new HashMap<>();
        ResultsDispatchRoomDetailsRespVO queryVO = createBaseQueryVO(startTime, endTime);

        // 查询所有数据源
        queryAllDataSources(params, queryVO);

        // 计算所有需要的值
        calculateAllRequiredValues(params);

        return params;
    }

    /**
     * 创建基础查询VO
     */
    private ResultsDispatchRoomDetailsRespVO createBaseQueryVO(String startTime, String endTime) {
        ResultsDispatchRoomDetailsRespVO vo = new ResultsDispatchRoomDetailsRespVO();
        vo.setStartSamplingTime(startTime);
        vo.setEndSamplingTime(endTime);
        return vo;
    }

    /**
     * 查询所有数据源
     */
    private void queryAllDataSources(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 英坪站送选数据
        queryYingpingStationData(params, queryVO);

        // 磨坊站送选数据
        queryMofangStationData(params, queryVO);

        // 外购送选数据
        queryExternalPurchaseData(params, queryVO);

        // 大塘送选数据
        queryDatangStationData(params, queryVO);

        // 穿岩洞送选数据
        queryChuanyandongStationData(params, queryVO);
    }

    /**
     * 查询英坪站送选数据
     */
    private void queryYingpingStationData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 磨坊寨子
        queryAndPutData(params, queryVO, "英坪送选", "磨坊寨子", "英坪站送选", "B23", "C23", "D23", "E23", "F23");

        // 三标段
        queryAndPutData(params, queryVO, "英坪送选", "三标段", "英坪站送选", "H23", "I23", "J23", "K23", "L23");

        // 双碑坟
        queryAndPutData(params, queryVO, "英坪送选", "双碑坟", "英坪站送选", "CB23", "CC23", "CD23", "CE23", "CF23");

        // 恒浩公司 (外购)
        queryAndPutData(params, queryVO, "英坪送选", "恒浩公司", "外购送选", "AF22", "AG22", "AH22", "AI22", "AJ22");

        // 有福公司 (外购)
        queryAndPutData(params, queryVO, "英坪送选", "有福公司", "外购送选", "AL23", "AM23", "AN23", "AO23", "AP23");

        // 婆子沟 (外购)
        queryAndPutData(params, queryVO, "英坪送选", "婆子沟", "外购送选", "CH23", "CI23", "CJ23", "CK23", "CL23");
    }

    /**
     * 查询磨坊站送选数据
     */
    private void queryMofangStationData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 婆子沟
        queryAndPutData(params, queryVO, "磨坊送选", "婆子沟", "磨坊站送选", "N23", "O23", "P23", "Q23", "R23");

        // 鸭棚洞
        queryAndPutData(params, queryVO, "磨坊送选", "鸭棚洞", "磨坊站送选", "T23", "U23", "V23", "W23", "X23");

        // 磨坊寨子
        queryAndPutData(params, queryVO, "磨坊送选", "磨坊寨子", "磨坊站送选", "Z23", "AA23", "AB23", "AC23", "AD23");

        // 青岗山
        queryAndPutData(params, queryVO, "磨坊送选", "青岗山", "磨坊站送选", "CN23", "CO23", "CP23", "CQ23", "CR23");

        // 婆子沟 (外购)
        queryAndPutData(params, queryVO, "磨坊送选", "婆子沟", "外购送选", "AR23", "AS23", "AT23", "AU23", "AV23");
    }

    /**
     * 查询外购送选数据
     */
    private void queryExternalPurchaseData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 已在外购相关的查询在英坪站和磨坊站中处理
    }

    /**
     * 查询大塘送选数据
     */
    private void queryDatangStationData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 双山坪
        queryAndPutData(params, queryVO, "大塘送选", "", "外购送选", "双山坪", "AX22", "AY22", "AZ22", "BA22", "BB22");

        // 有福公司
        queryAndPutData(params, queryVO, "大塘送选", "有福公司", "外购送选", "", "BD23", "BE23", "BF23", "BG23", "BH23");
    }

    /**
     * 查询穿岩洞送选数据
     */
    private void queryChuanyandongStationData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO) {
        // 双山坪
        queryAndPutData(params, queryVO, "穿岩洞送选", "", "外购送选", "双山坪", "BJ22", "BK22", "BL22", "BM22", "BN22");

        // 有福公司
        queryAndPutData(params, queryVO, "穿岩洞送选", "有福公司", "外购送选", "", "BP23", "BQ23", "BR23", "BS23", "BT23");
    }

    /**
     * 通用数据查询方法 (无 miningUnit)
     */
    private void queryAndPutData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO,
                                 String supplier, String field, String property,
                                 String qtyKey, String p2o5Key, String mgoKey, String r2o3Key, String sio2Key) {
        queryVO.setMiningSupplier(supplier);
        queryVO.setMiningField(field);
        queryVO.setOreProperty(property);
        queryVO.setMiningUnit(null);

        Map<String, BigDecimal> result = resultsDispatchRoomDetailsService.getConsignmentProcessingSum(queryVO);

        params.put(qtyKey, getSafeValue(result, "total_quantity"));
        params.put(p2o5Key, getSafeValue(result, "p2o5"));
        params.put(mgoKey, getSafeValue(result, "mgo"));
        params.put(r2o3Key, getSafeValue(result, "r2o3"));
        params.put(sio2Key, getSafeValue(result, "sio2"));
    }

    /**
     * 通用数据查询方法 (有 miningUnit)
     */
    private void queryAndPutData(Map<String, BigDecimal> params, ResultsDispatchRoomDetailsRespVO queryVO,
                                 String supplier, String field, String property, String unit,
                                 String qtyKey, String p2o5Key, String mgoKey, String r2o3Key, String sio2Key) {
        queryVO.setMiningSupplier(supplier);
        queryVO.setMiningField(field);
        queryVO.setOreProperty(property);
        queryVO.setMiningUnit(unit);

        Map<String, BigDecimal> result = resultsDispatchRoomDetailsService.getConsignmentProcessingSum(queryVO);

        params.put(qtyKey, getSafeValue(result, "total_quantity"));
        params.put(p2o5Key, getSafeValue(result, "p2o5"));
        params.put(mgoKey, getSafeValue(result, "mgo"));
        params.put(r2o3Key, getSafeValue(result, "r2o3"));
        params.put(sio2Key, getSafeValue(result, "sio2"));
    }

    /**
     * 合并所有时间维度的数据
     */
    private Map<String, BigDecimal> mergeAllData(Map<String, BigDecimal> currentMonth,
                                                 Map<String, BigDecimal> yearToDate,
                                                 Map<String, BigDecimal> lastYear) {
        Map<String, BigDecimal> merged = new HashMap<>(currentMonth);

        // 本年累计数据映射
        mapYearToDateData(merged, yearToDate);

        // 去年同期数据映射
        mapLastYearData(merged, lastYear, yearToDate);

        return merged;
    }

    /**
     * 映射本年累计数据
     */
    private void mapYearToDateData(Map<String, BigDecimal> target, Map<String, BigDecimal> source) {
        // 自产矿石数据
        target.put("L39", source.get("B24"));
        target.put("K39", source.get("C24"));
        target.put("K40", source.get("D24"));
        target.put("K41", source.get("E24"));
        target.put("K42", source.get("F24"));

        // 外部矿石利用数据
        target.put("L43", source.get("AR27"));
        target.put("K43", source.get("AS27"));
        target.put("K44", source.get("AT27"));
        target.put("K45", source.get("AU27"));
        target.put("K46", source.get("AV27"));

        // 有福公司自产矿石数据
        target.put("L51", source.get("BV25"));
        target.put("K51", source.get("BW25"));
        target.put("K52", source.get("BX25"));
        target.put("K53", source.get("BY25"));
        target.put("K54", source.get("BZ25"));

        // 有福公司外部矿石利用数据
        target.put("L55", source.get("AR26"));
        target.put("K55", source.get("AS26"));
        target.put("K56", source.get("AT26"));
        target.put("K57", source.get("AU26"));
        target.put("K58", source.get("AV26"));
    }

    /**
     * 映射去年同期数据
     */
    private void mapLastYearData(Map<String, BigDecimal> target, Map<String, BigDecimal> lastYear, Map<String, BigDecimal> yearToDate) {
        // 自产矿石去年同期数据
        target.put("I39", lastYear.get("B24"));
        target.put("H39", lastYear.get("C24"));
        target.put("H40", lastYear.get("D24"));
        target.put("H41", lastYear.get("E24"));
        target.put("H42", lastYear.get("F24"));

        // 外部矿石利用去年同期数据 (使用本年累计数据作为占位)
        target.put("I43", yearToDate.get("AR27"));
        target.put("H43", yearToDate.get("AS27"));
        target.put("H44", yearToDate.get("AT27"));
        target.put("H45", yearToDate.get("AU27"));
        target.put("H46", yearToDate.get("AV27"));

        // 有福公司自产矿石去年同期数据
        target.put("I51", yearToDate.get("BV25"));
        target.put("H51", yearToDate.get("BW25"));
        target.put("H52", yearToDate.get("BX25"));
        target.put("H53", yearToDate.get("BY25"));
        target.put("H54", yearToDate.get("BZ25"));

        // 有福公司外部矿石利用去年同期数据
        target.put("I55", yearToDate.get("AR26"));
        target.put("H55", yearToDate.get("AS26"));
        target.put("H56", yearToDate.get("AT26"));
        target.put("H57", yearToDate.get("AU26"));
        target.put("H58", yearToDate.get("AV26"));
    }

    // ========== 以下计算方法保持不变，但可以进一步优化 ==========

    /**
     * 计算所有需要的值
     */
    private void calculateAllRequiredValues(Map<String, BigDecimal> params) {
        calculateB24Series(params);    // 购进磷矿石
        calculateAR27Series(params);   // 外购送选部分
        calculateBV25Series(params);   // 英坪站送选 + 磨坊站送选
        calculateAR26Series(params);   // 外购送选汇总
    }

    /**
     * 计算 B24 系列 (购进磷矿石)
     */
    private void calculateB24Series(Map<String, BigDecimal> params) {
        BigDecimal B24 = getSafeValue(params, "B23")
                .add(getSafeValue(params, "Z23"))
                .add(getSafeValue(params, "T23"))
                .add(getSafeValue(params, "H23"))
                .add(getSafeValue(params, "N23"));
        params.put("B24", setScale(B24));

        params.put("C24", calculateWeightedAverage(
                getSafeValue(params, "B23"), getSafeValue(params, "C23"),
                getSafeValue(params, "Z23"), getSafeValue(params, "AA23"),
                getSafeValue(params, "T23"), getSafeValue(params, "U23"),
                getSafeValue(params, "H23"), getSafeValue(params, "I23"),
                getSafeValue(params, "N23"), getSafeValue(params, "O23"),
                B24
        ));

        params.put("D24", calculateWeightedAverage(
                getSafeValue(params, "B23"), getSafeValue(params, "D23"),
                getSafeValue(params, "Z23"), getSafeValue(params, "AB23"),
                getSafeValue(params, "T23"), getSafeValue(params, "V23"),
                getSafeValue(params, "H23"), getSafeValue(params, "J23"),
                getSafeValue(params, "N23"), getSafeValue(params, "P23"),
                B24
        ));

        params.put("E24", calculateWeightedAverage(
                getSafeValue(params, "B23"), getSafeValue(params, "E23"),
                getSafeValue(params, "Z23"), getSafeValue(params, "AC23"),
                getSafeValue(params, "T23"), getSafeValue(params, "W23"),
                getSafeValue(params, "H23"), getSafeValue(params, "K23"),
                getSafeValue(params, "N23"), getSafeValue(params, "Q23"),
                B24
        ));

        params.put("F24", calculateWeightedAverage(
                getSafeValue(params, "B23"), getSafeValue(params, "F23"),
                getSafeValue(params, "Z23"), getSafeValue(params, "AD23"),
                getSafeValue(params, "T23"), getSafeValue(params, "X23"),
                getSafeValue(params, "H23"), getSafeValue(params, "L23"),
                getSafeValue(params, "N23"), getSafeValue(params, "R23"),
                B24
        ));
    }

    /**
     * 计算 AR27 系列 (外购送选部分)
     */
    private void calculateAR27Series(Map<String, BigDecimal> params) {
        BigDecimal AR25 = getSafeValue(params, "BJ22")
                .add(getSafeValue(params, "AF22"))
                .add(getSafeValue(params, "AX22"));
        params.put("AR25", setScale(AR25));

        BigDecimal AR27 = AR25;
        params.put("AR27", setScale(AR27));

        params.put("AS25", calculateWeightedAverageThree(
                getSafeValue(params, "BJ22"), getSafeValue(params, "BK22"),
                getSafeValue(params, "AF22"), getSafeValue(params, "AG22"),
                getSafeValue(params, "AX22"), getSafeValue(params, "AY22"),
                AR25
        ));

        params.put("AT25", calculateWeightedAverageThree(
                getSafeValue(params, "BJ22"), getSafeValue(params, "BL22"),
                getSafeValue(params, "AF22"), getSafeValue(params, "AH22"),
                getSafeValue(params, "AX22"), getSafeValue(params, "AZ22"),
                AR25
        ));

        params.put("AU25", calculateWeightedAverageThree(
                getSafeValue(params, "BJ22"), getSafeValue(params, "BM22"),
                getSafeValue(params, "AF22"), getSafeValue(params, "AI22"),
                getSafeValue(params, "AX22"), getSafeValue(params, "BA22"),
                AR25
        ));

        params.put("AV25", calculateWeightedAverageThree(
                getSafeValue(params, "BJ22"), getSafeValue(params, "BN22"),
                getSafeValue(params, "AF22"), getSafeValue(params, "AJ22"),
                getSafeValue(params, "AX22"), getSafeValue(params, "BB22"),
                AR25
        ));

        params.put("AS27", calculateFinalResult(AR25, getSafeValue(params, "AS25"), AR27));
        params.put("AT27", calculateFinalResult(AR25, getSafeValue(params, "AT25"), AR27));
        params.put("AU27", calculateFinalResult(AR25, getSafeValue(params, "AU25"), AR27));
        params.put("AV27", calculateFinalResult(AR25, getSafeValue(params, "AV25"), AR27));
    }

    /**
     * 计算 BV25 系列 (英坪站送选 + 磨坊站送选)
     */
    private void calculateBV25Series(Map<String, BigDecimal> params) {
        BigDecimal BV24 = getSafeValue(params, "BV23").add(getSafeValue(params, "CB23"));
        params.put("BV24", setScale(BV24));

        BigDecimal CN24 = getSafeValue(params, "CN23")
                .add(getSafeValue(params, "CT23"))
                .add(getSafeValue(params, "CZ23"));
        params.put("CN24", setScale(CN24));

        BigDecimal BV25 = BV24.add(CN24);
        params.put("BV25", setScale(BV25));

        // 计算各指标
        calculateBV25Indicators(params, BV24, CN24, BV25);
    }

    /**
     * 计算 BV25 系列的各项指标
     */
    private void calculateBV25Indicators(Map<String, BigDecimal> params, BigDecimal BV24, BigDecimal CN24, BigDecimal BV25) {
        // P2O5
        BigDecimal BW24 = calculateWeightedAverage(
                getSafeValue(params, "BV23"), getSafeValue(params, "BW23"),
                getSafeValue(params, "CB23"), getSafeValue(params, "CC23"),
                BV24
        );
        BigDecimal CO24 = calculateWeightedAverageThree(
                getSafeValue(params, "CN23"), getSafeValue(params, "CO23"),
                getSafeValue(params, "CT23"), getSafeValue(params, "CU23"),
                getSafeValue(params, "CZ23"), getSafeValue(params, "DA23"),
                CN24
        );
        params.put("BW25", calculateWeightedAverage(BV24, BW24, CN24, CO24, BV25));

        // MgO
        BigDecimal BX24 = calculateWeightedAverage(
                getSafeValue(params, "BV23"), getSafeValue(params, "BX23"),
                getSafeValue(params, "CB23"), getSafeValue(params, "CD23"),
                BV24
        );
        BigDecimal CP24 = calculateWeightedAverageThree(
                getSafeValue(params, "CN23"), getSafeValue(params, "CP23"),
                getSafeValue(params, "CT23"), getSafeValue(params, "CV23"),
                getSafeValue(params, "CZ23"), getSafeValue(params, "DB23"),
                CN24
        );
        params.put("BX25", calculateWeightedAverage(BV24, BX24, CN24, CP24, BV25));

        // R2O3
        BigDecimal BY24 = calculateWeightedAverage(
                getSafeValue(params, "BV23"), getSafeValue(params, "BY23"),
                getSafeValue(params, "CB23"), getSafeValue(params, "CE23"),
                BV24
        );
        BigDecimal CQ24 = calculateWeightedAverageThree(
                getSafeValue(params, "CN23"), getSafeValue(params, "CQ23"),
                getSafeValue(params, "CT23"), getSafeValue(params, "CW23"),
                getSafeValue(params, "CZ23"), getSafeValue(params, "DC23"),
                CN24
        );
        params.put("BY25", calculateWeightedAverage(BV24, BY24, CN24, CQ24, BV25));

        // SiO2
        BigDecimal BZ24 = calculateWeightedAverage(
                getSafeValue(params, "BV23"), getSafeValue(params, "BZ23"),
                getSafeValue(params, "CB23"), getSafeValue(params, "CF23"),
                BV24
        );
        BigDecimal CR24 = calculateWeightedAverageThree(
                getSafeValue(params, "CN23"), getSafeValue(params, "CR23"),
                getSafeValue(params, "CT23"), getSafeValue(params, "CX23"),
                getSafeValue(params, "CZ23"), getSafeValue(params, "DD23"),
                CN24
        );
        params.put("BZ25", calculateWeightedAverage(BV24, BZ24, CN24, CR24, BV25));
    }

    /**
     * 计算 AR26 系列 (外购送选汇总)
     */
    private void calculateAR26Series(Map<String, BigDecimal> params) {
        BigDecimal AR26 = getSafeValue(params, "AL23")
                .add(getSafeValue(params, "BD23"))
                .add(getSafeValue(params, "BP23"))
                .add(getSafeValue(params, "AR23"));
        params.put("AR26", setScale(AR26));

        params.put("AS26", calculateWeightedAverageFour(
                getSafeValue(params, "BD23"), getSafeValue(params, "BE23"),
                getSafeValue(params, "BP23"), getSafeValue(params, "BQ23"),
                getSafeValue(params, "AL23"), getSafeValue(params, "AM23"),
                getSafeValue(params, "AR23"), getSafeValue(params, "AS23"),
                AR26
        ));

        params.put("AT26", calculateWeightedAverageFour(
                getSafeValue(params, "BD23"), getSafeValue(params, "BF23"),
                getSafeValue(params, "BP23"), getSafeValue(params, "BR23"),
                getSafeValue(params, "AL23"), getSafeValue(params, "AN23"),
                getSafeValue(params, "AR23"), getSafeValue(params, "AT23"),
                AR26
        ));

        params.put("AU26", calculateWeightedAverageFour(
                getSafeValue(params, "BD23"), getSafeValue(params, "BG23"),
                getSafeValue(params, "BP23"), getSafeValue(params, "BS23"),
                getSafeValue(params, "AL23"), getSafeValue(params, "AO23"),
                getSafeValue(params, "AR23"), getSafeValue(params, "AU23"),
                AR26
        ));

        params.put("AV26", calculateWeightedAverageFour(
                getSafeValue(params, "BD23"), getSafeValue(params, "BH23"),
                getSafeValue(params, "BP23"), getSafeValue(params, "BT23"),
                getSafeValue(params, "AL23"), getSafeValue(params, "AP23"),
                getSafeValue(params, "AR23"), getSafeValue(params, "AV23"),
                AR26
        ));
    }

    // ========== 数学计算工具方法 ==========

    /**
     * 通用加权平均值计算方法 (5组数据)
     */
    private BigDecimal calculateWeightedAverage(BigDecimal q1, BigDecimal v1, BigDecimal q2, BigDecimal v2,
                                                BigDecimal q3, BigDecimal v3, BigDecimal q4, BigDecimal v4,
                                                BigDecimal q5, BigDecimal v5, BigDecimal total) {
        return safeDivide(
                q1.multiply(v1).add(q2.multiply(v2)).add(q3.multiply(v3))
                        .add(q4.multiply(v4)).add(q5.multiply(v5)),
                total
        );
    }

    /**
     * 通用加权平均值计算方法 (2组数据)
     */
    private BigDecimal calculateWeightedAverage(BigDecimal q1, BigDecimal v1, BigDecimal q2, BigDecimal v2, BigDecimal total) {
        return safeDivide(q1.multiply(v1).add(q2.multiply(v2)), total);
    }

    /**
     * 通用加权平均值计算方法 (3组数据)
     */
    private BigDecimal calculateWeightedAverageThree(BigDecimal q1, BigDecimal v1, BigDecimal q2, BigDecimal v2,
                                                     BigDecimal q3, BigDecimal v3, BigDecimal total) {
        return safeDivide(q1.multiply(v1).add(q2.multiply(v2)).add(q3.multiply(v3)), total);
    }

    /**
     * 通用加权平均值计算方法 (4组数据)
     */
    private BigDecimal calculateWeightedAverageFour(BigDecimal q1, BigDecimal v1, BigDecimal q2, BigDecimal v2,
                                                    BigDecimal q3, BigDecimal v3, BigDecimal q4, BigDecimal v4, BigDecimal total) {
        return safeDivide(q1.multiply(v1).add(q2.multiply(v2)).add(q3.multiply(v3)).add(q4.multiply(v4)), total);
    }

    /**
     * 计算最终结果 (*27系列)
     */
    private BigDecimal calculateFinalResult(BigDecimal AR25, BigDecimal value, BigDecimal AR27) {
        return safeDivide(AR25.multiply(value), AR27);
    }

    /**
     * 安全除法计算
     */
    private BigDecimal safeDivide(BigDecimal numerator, BigDecimal denominator) {
        if (denominator == null || denominator.compareTo(BigDecimal.ZERO) == 0) {
            return ZERO;
        }
        try {
            return numerator.divide(denominator, SCALE, ROUNDING_MODE);
        } catch (Exception e) {
            log.warn("除法计算失败: {} / {}, 返回0", numerator, denominator, e);
            return ZERO;
        }
    }

    /**
     * 安全获取BigDecimal值
     */
    private BigDecimal getSafeValue(Map<String, BigDecimal> map, String key) {
        if (map == null) {
            return ZERO;
        }
        BigDecimal value = map.get(key);
        return value != null ? setScale(value) : ZERO;
    }

    /**
     * 设置小数位数
     */
    private BigDecimal setScale(BigDecimal value) {
        return value != null ? value.setScale(SCALE, ROUNDING_MODE) : ZERO;
    }

    /**
     * 获取统计周期时间范围（上月25号 - 本月24号）
     */
    public Map<String, String> getStatisticsPeriodRange() {
        LocalDateTime now = LocalDateTime.now();

        LocalDateTime startTime = now.minusMonths(1).withDayOfMonth(25)
                .withHour(0).withMinute(0).withSecond(0).withNano(0);

        LocalDateTime endTime = now.withDayOfMonth(24)
                .withHour(23).withMinute(59).withSecond(59).withNano(999000000);

        Map<String, String> range = new HashMap<>();
        range.put("startTime", startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
        range.put("endTime", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));

        return range;
    }
}
